package com.lck.main.game;

import com.lck.main.view.GamePanel;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.Serializable;

public abstract class Chess implements Serializable {
    //定义常量，只能在定义时或代码块中修改值，其他不允许修改
    private static final int SIZE = 30;//棋子大小
    private static final int MARGIN = 20;//棋盘外间距
    private static final int SPACE = 40;//棋子间距
    private String name; //棋子角色
    private String suffix = ".png"; //后缀名
    protected int player; //阵营
    private int x, y;//棋子绘制时的坐标位置
    protected Point p;//棋子网格坐标
    private Point initP;//棋子的网格坐标，初始位置，不可改变
    private int index; //保存每个棋子的索引位置

    public Chess(String name, int player, Point p) {
        this.name = name;
        this.player = player;
        setP(p);
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    public int getPlayer() {
        return player;
    }

    public void setPlayer(int player) {
        this.player = player;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public Point getP() {
        return p;
    }

    public void setP(Point p) {
        this.p = (Point) p.clone();
        if (initP == null) {
            initP = this.p;
        }
        calXY();
    }

    public void draw(Graphics g, JPanel panel) {
        String path = "pic" + File.separator;
        g.drawImage(getImage(path + name + player + suffix),
                x,
                y,
                SIZE,
                SIZE,
                panel);
    }

    public Image getImage(String path) {
        return Toolkit.getDefaultToolkit().getImage(path);
    }

    /**
     * 计算xy的绘制坐标
     */
    public void calXY() {
        x = MARGIN - SIZE / 2 + SPACE * (p.x - 1);
        y = MARGIN - SIZE / 2 + SPACE * (p.y - 1);
    }

    /**
     * 绘制选中棋子边框
     *
     * @param g
     */
    public void drawRect(Graphics g) {
        g.drawRect(x, y, SIZE, SIZE);
    }

    /**
     * 判断棋子初试在上半边还是下半边
     * 1：上
     * 2：下
     * 0不在里面
     *
     * @return
     */
    public int isUpOrDown() {
        //上面和下面
        if (initP.y < 6) {
            //上面
            return 1;
        } else if (initP.y > 5) {
            //下面
            return 2;
        }
        return 0;
    }

    /**
     * 判断是否在王宫范围内
     *
     * @param tp
     * @return
     */
    public boolean isHome(Point tp) {
        if (tp.x < 4 || tp.x > 6) {
            return false;
        }
        int upOrDown = isUpOrDown();
        if (upOrDown == 1) {
            //上面
            if (tp.y > 3 || tp.y < 1) {
                return false;
            }
        } else if (upOrDown == 2) {
            //下面
            if (tp.y > 10 || tp.y < 8) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是走直线还是斜线还是都不是
     * 1：正斜线
     * 2：y轴直线
     * 3：x轴直线
     * 0：往x方向走日字
     * -1：往y轴方向走日字
     * -2：都不是
     * @param tp
     * @return
     */
    public int line(Point tp) {
        //x轴直线，还是y轴
        if (p.y == tp.y) {
            //x
            return 3;
        } else if (p.x == tp.x) {
            //y
            return 2;
        } else if (Math.abs(p.y - tp.y) == Math.abs(p.x - tp.x)) {
            //走的斜线
            return 1;
        } else {
            //走日字
            if (Math.abs(p.x - tp.x) == 2 && Math.abs(p.y - tp.y) == 1){
                //x 走日字
                return 0;
            } else if (Math.abs(p.x - tp.x) == 1 && Math.abs(p.y - tp.y) == 2){
                //y 走日字
                return -1;
            }
        }
        return -2;
    }

    /**
     * 获取走的步数
     * @param tp
     * @return
     */
    public int getStep(Point tp){
        int line = line(tp);
        if (line == 3){
            //在x轴
            return Math.abs(tp.x - p.x);
        } else if (line == 2 || line == 1){
            //y或正斜线
            return Math.abs(p.y - tp.y);
        }
        return 0;
    }

    /**
     * 判断目标点是否过河
     * @param tp
     * @return
     */
    public boolean isOverRiver(Point tp){
        if (isUpOrDown() == 1){
            //上面
            System.out.println(tp.y > 5);
            if (tp.y < 6)
            return false;
        } else if (isUpOrDown() == 2){
            //下面
            if (tp.y > 5)
            return false;
        }
        return true;
    }

    /**
     * 判断象和马是否蹩脚
     * @param tp
     * @param gamePanel
     * @return
     */
    public boolean isBieJiao(Point tp, GamePanel gamePanel){
        Point center = new Point();//中心点
        if ("xiang".equals(name)){
            center.x  = (p.x + tp.x) /2;
            center.y  = (p.y + tp.y) /2;
            System.out.println(gamePanel.getChessByP(center) != null);
            return gamePanel.getChessByP(center)!=null;
        } else if ("ma".equals(name)){
            int line = line(tp);
            if (line == 0){
                //x
                center.x = (p.x + tp.x) /2;
                center.y  = p.y;
            } else if (line == -1){
                //y
                center.y = (p.y + tp.y) /2;
                center.x  = p.x;
            }
            return gamePanel.getChessByP(center)!=null;
        }
        return false;
    }

    /**
     * 专门用来计算起点到目标点之间的棋子数量，不计算起点和目标点上的位置
     * @param tp
     * @return
     */
    public int getCount(Point tp,GamePanel gamePanel) {
        int start = 0;
        int end = 0;
        int count = 0;
        int line = line(tp);
        Point ps = new Point();
        if (line == 2){
            //y
            ps.x = tp.x;
            if (tp.y > p.y){
                //从上往下走
                start = p.y + 1;
                end = tp.y;
            } else {
                //从下往上走
                start = tp.y + 1;
                end = p.y;
            }
            for (int i = start; i < end ;i++){
                ps.y = i;
                if (gamePanel.getChessByP(ps)!=null){
                    count ++;
                }
            }
        } else if (line == 3){
            //x
            ps.y = tp.y;
            if (tp.x > p.x){
                //从左向右
                start = p.x + 1;
                end = tp.x;
            } else {
                //从右向左
                start = tp.x + 1;
                end = p.x;
            }
            for (int i = start; i < end ;i++){
                ps.x = i;
                if (gamePanel.getChessByP(ps)!=null){
                    count ++;
                }
            }
        }
        return count;
    }

    /**
     * 判断是否前进
     * @param tp
     * @return
     */
    public boolean isForward(Point tp){
        if (isUpOrDown() == 1){
            //上
            if (tp.y > p.y){
                //前进
                return true;
            }
        }else if (isUpOrDown() == 2){
            //下
            if (tp.y < p.y){
                //前进
                return true;
            }
        }
        return false;
    }

    public boolean isBack(Point tp){
        if (isUpOrDown() == 1){
            //上
            if (tp.y < p.y){
                //前进
                return true;
            }
        }else if (isUpOrDown() == 2){
            //下
            if (tp.y > p.y){
                //前进
                return true;
            }
        }
        return false;
    }

    /**
     * 判断棋子是否可以移动到指定位置
     * @param tp
     * @return
     */
    public abstract boolean isAbleMoved(Point tp,GamePanel gamePanel);

    /**
     * 根据xy坐标计算网格坐标
     * @param x
     * @param y
     */
    public static Point getPointFromXY(int x, int y){
        Point p = new Point();
        p.x = (x - MARGIN + SIZE / 2) / SPACE + 1;
        p.y = (y - MARGIN + SIZE / 2) / SPACE + 1;
        if (p.x < 1 || p.x > 10 || p.y < 1 || p.y > 11){
            return null;
        }
        return p;
    }
    /**
     * 反转网络坐标
     */
    public void reverse(){
        p.x = 10 - p.x;
        p.y = 11 - p.y;
        initP = p;
        calXY();
    }
}
